#ifndef TextStyles_First
#define TextStyles_First
#ifdef __GNUG__
#pragma interface
#endif

#include "OrdColl.h"
#include "Font.h"
#include "Ink.h"

class ParaStyleManager;
class CharStyleManager;

enum TxtCharProp {    // modes for SetCharStyle
	eTxTPFont   = BIT(0),
	eTxTPFace   = BIT(1),
	eTxtPSize   = BIT(2),
	eTxtPAddSize= BIT(3),
	eTxtPInk    = BIT(4),
	eTxtPSub    = BIT(5),
	eTxtCPFontAll= eTxTPFont + eTxTPFace + eTxtPSize,
	eTxtCPropAll= eTxtCPFontAll + eTxtPInk // change all
};

const bool
	cStyleXorMode= TRUE,
	cStyleOrMode= !cStyleXorMode;
		
//---- CharStyleSpec -----------------------------------------------------------

class CharStyleSpec {
public:
	CharStyleSpec();
	CharStyleSpec(Font *fp, Ink *c= ePatBlack, bool mode= cStyleXorMode);
	CharStyleSpec(GrFont ft, GrFace fc, int sz, Ink *c= ePatBlack, bool mode= cStyleXorMode);
public:
	GrFont font;
	GrFace face;
	short size;
	Ink *ink;
	bool xor; // apply face change in an XOR or OR fashion
};

//---- CharStyleChange ---------------------------------------------------------

class CharStyleChange {
public:
	TxtCharProp what;
	CharStyleSpec st;
};

//---- CharDesc ----------------------------------------------------------------

class CharDesc {
public:
	void GetFontProp(GrFont &fid, GrFace &face, int &size);
public:
	Font *fp;
	Ink* ink;
	int subScript;
};

//---- CharStyle ---------------------------------------------------------------

class CharStyle: public Object {
friend CharStyleManager;
public:
	MetaDef(CharStyle);

	friend CharStyle *new_CharStyle(Font *f= gSysFont, Ink *i= ePatBlack);
	friend CharStyle *new_CharStyle(GrFont ft, GrFace fc, int size,
							Ink *i= ePatBlack);

	bool IsEqual(Object*);
	void GetProperties(CharDesc &cd);
	Font *GetFont();
	Ink *GetInk();
	OStream& PrintOn(OStream&);
	Object *ReadAndMap(IStream&);
	Object *deepclone();

private:
	CharDesc c;
	CharStyle(int, CharDesc &cd);
	~CharStyle();
};

inline Font *CharStyle::GetFont()
	{ return c.fp; }

inline Ink *CharStyle::GetInk()
	{ return c.ink; }

//---- CharStyleManager --------------------------------------------------------

class CharStyleManager: public OrdCollection {
public:
	MetaDef(CharStyleManager);
	CharStyleManager();
	~CharStyleManager();
	CharStyle *MakeCharStyle(CharDesc &c);
	CharStyle *ChangeProperty(CharStyle *cs, TxtCharProp what, CharStyleSpec st);
	CharStyle *Default();
};

//---- SmartCharStyles ---------------------------------------------------------

class SmartCharStyles {
public:
	SmartCharStyles()
		{}
	~SmartCharStyles()
		{ SafeDelete(cm); }
	CharStyleManager *operator -> ()
		{ return make(); }
	operator CharStyleManager* ()
		{ return make(); }
private:
	CharStyleManager *cm;
	CharStyleManager *make();
};

extern SmartCharStyles gCharStyles;

//---- Paragraph Styles --------------------------------------------------------

enum TxtParaAlign {    // paragraph alignment
	eTxtParaLeft,
	eTxtParaRight,
	eTxtParaCenter,
	eTxtParaJustified
};

enum TxtParaFlags {    // paragraph breaking options
	eTxtPFlagNoBreak= BIT(0),
	eTxtPFlagKeep= BIT(1)
};

enum TxtParaProp {    // modes for SetParaProperty
	eTxtPAlign  = BIT(0),
	eTxtPLeft   = BIT(1),
	eTxtPRight  = BIT(2),
	eTxtPFirstIndent= BIT(3),
	eTxtPSpacing= BIT(4),
	eTxtPSpaceBefore= BIT(5),
	eTxtPNoBreak= BIT(6),
	eTxtPKeepNext= BIT(7),
	eTxtPSpaceAfter= BIT(8),
	eTxtPAddTab = BIT(9),
	eTxtPAddTabC= BIT(10),
	eTxtPAddTabR= BIT(11),
	eTxtPAddTabD= BIT(12),
	eTxtPRemoveTab= BIT(13),
	eTxtPReplaceTabs= BIT(14),
	eTxtPEmptyTabs= BIT(15),

	eTxtPPropAll= eTxtPAlign + eTxtPLeft + eTxtPRight +
		eTxtPFirstIndent + eTxtPSpacing + eTxtPSpaceBefore +
		eTxtPSpaceAfter + eTxtPReplaceTabs + eTxtPKeepNext +
		eTxtPNoBreak
};

enum TxtTabStop {    // tab types
	eTxtTLeft,
	eTxtTRight,
	eTxtTCenter,
	eTxtTDecimal
};

class TabStop {
public:
	TxtTabStop kind;
	short x;
};

//---- ParaTabs ----------------------------------------------------------------

class ParaTabs {
public:
	ParaTabs(const ParaTabs &);
	ParaTabs();
	~ParaTabs();
	bool IsEqual(ParaTabs &t);
	void Copy(const ParaTabs &t);
	void Add(int x, TxtTabStop kind);
	void Remove(int x);
	void Move(int from, int to);
	void operator= (const ParaTabs &pt);
	friend OStream& operator<< (OStream&, ParaTabs &p);
	friend IStream& operator>> (IStream&, ParaTabs &p);
private:
	friend bool operator== (ParaTabs p1, ParaTabs p2);
public:
	int ntabs;
	TabStop *stops;
	int size;
};

//---- ParaDesc ----------------------------------------------------------------

class ParaDesc {
public:
	void SetProperty(TxtParaProp p, int val);
	bool TestFlag(TxtParaFlags f);

public:
	TxtParaAlign alignment;
	int flags;
	int rightIndent;
	int leftIndent;
	int firstIndent;
	int spacing;
	int spaceBefore;
	int spaceAfter;
	ParaTabs tabs;
};

//---- ParaStyle ---------------------------------------------------------------

class ParaStyle: public Object {
friend ParaStyleManager;
public:
	MetaDef(ParaStyle);

	friend ParaStyle* new_ParaStyle(TxtParaAlign a= eTxtParaLeft, int ri= 0,
		int li= 0, int fi= 0, int sp= 12, int sb= 0, int sa= 0,
		int flags= 0, ParaTabs *t= 0);
	friend ParaStyle* new_ParaStyle(ParaDesc&);

	bool IsEqual(Object*);
	OStream& PrintOn(OStream&);
	Object *ReadAndMap(IStream&);
	Object *deepclone();
	void CopyProperties(ParaDesc&);
	int GetProperty(TxtParaProp what);
	const ParaTabs &GetTabs();

private:
	ParaStyle(int, ParaDesc&);
	~ParaStyle();
private:
	ParaDesc p;
};

//---- ParaStyleManager --------------------------------------------------------

class ParaStyleManager: public OrdCollection {
public:
	MetaDef(ParaStyleManager);
	ParaStyleManager();
	~ParaStyleManager();
	ParaStyle *MakeParaStyle(ParaDesc &p);
	ParaStyle *ChangeProperty(ParaStyle *pp, TxtParaProp what,
							const ParaDesc &pd);
};

//---- SmartParaStyles ---------------------------------------------------------

class SmartParaStyles {
public:
	SmartParaStyles()
		{}
	~SmartParaStyles()
		{ SafeDelete(pm); }
	ParaStyleManager *operator -> ()
		{ return make(); }
	operator ParaStyleManager* ()
		{ return make(); }
private:
	ParaStyleManager *pm;
	ParaStyleManager *make();
};

extern SmartParaStyles gParaStyles;

#endif
